package com.own.component.store.local.method;

import com.own.component.store.core.method.StoreSet;
import com.own.component.store.core.property.LocalStoreProperty;
import com.own.component.store.local.method.scheduler.StoreSetScheduler;
import com.own.component.store.local.method.state.StoreState;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * DefaultLocalStoreSet
 *
 * @author chenxueli
 * @date 2022-06-15 03:14:15
 */
@Slf4j
public class DefaultLocalStoreSet<T> extends DefaultBaseStoreMethod<Set<T>> implements StoreSet<T> {

    private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(true);
    private final Lock writeLock = cacheLock.writeLock();
    private final Lock readLock = cacheLock.readLock();

    public DefaultLocalStoreSet() {
        super(new StoreState<>());
    }

    public DefaultLocalStoreSet(long delay) {
        super(new StoreState<>(), StoreSetScheduler.INSTANCE, delay);
    }

    public DefaultLocalStoreSet(LocalStoreProperty properties) {
        super(new StoreState<>(), StoreSetScheduler.INSTANCE, properties);
    }

    /**
     * 获取缓存的长度
     *
     * @param name 唯一key
     * @return 长度
     */
    @Override
    public Long size(String name) {
        readLock.lock();
        try {
            return (long) getStoreState().get(buildKey(name)).size();
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取所有的key
     *
     * @return 所有的key
     */
    @Override
    public Set<String> keySet() {
        readLock.lock();
        try {
            return getStoreState().keySet();
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取set集合
     *
     * @param name 唯一key
     * @return set集合
     */
    @Override
    public Set<T> members(String name) {
        readLock.lock();
        try {
            return getStoreState().get(buildKey(name));
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 插入值
     *
     * @param name  唯一key
     * @param value 值
     */
    @Override
    public void add(String name, T value) {
        writeLock.lock();
        try {
            if (!contains(name)) {
                getStoreState().set(buildKey(name), new HashSet<>());
            }
            getStoreState().get(buildKey(name)).add(value);
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 插入值
     *
     * @param name   唯一key
     * @param values 值列表
     */
    @Override
    public void add(String name, T... values) {
        writeLock.lock();
        try {
            if (!contains(name)) {
                getStoreState().set(buildKey(name), Stream.of(values).collect(Collectors.toSet()));
            } else {
                getStoreState().get(buildKey(name)).addAll(Stream.of(values).collect(Collectors.toSet()));
            }
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 是否包含
     *
     * @param name  唯一key
     * @param value 值
     * @return 是否包含
     */
    @Override
    public boolean contains(String name, T value) {
        readLock.lock();
        try {
            if (contains(name)) {
                return getStoreState().get(buildKey(name)).contains(value);
            }
            return false;
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 批量移除
     *
     * @param name   唯一key
     * @param values 值列表
     */
    @Override
    public void remove(String name, T... values) {
        writeLock.lock();
        try {
            if (contains(name)) {
                Arrays.asList(values).forEach(getStoreState().get(buildKey(name))::remove);
            }
        } finally {
            writeLock.unlock();
        }
    }

}
